package com.xing.lei.happy.thrid.flh.bigModel;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import okhttp3.*;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class BigModel extends WebSocketListener {
    // 地址与鉴权信息  https://spark-api.xf-yun.com/v1.1/chat   1.5地址  domain参数为general
    // 地址与鉴权信息  https://spark-api.xf-yun.com/v2.1/chat   2.0地址  domain参数为generalv2
    public static final String hostUrl = "https://spark-api.xf-yun.com/v1.1/chat";
    public static final String appid = "b2a710f5";
    public static final String apiSecret = "ZjhjYmE1MmU2YjYyNzE1NmE2NjE2MDZj";
    public static final String apiKey = "5575a1ee913155aa3a86b760fca9b371";

    public static String totalAnswer = ""; // 大模型的答案汇总

    // 环境治理的重要性  环保  人口老龄化  我爱我的祖国
    public static String NewQuestion = "";

    public static Gson returnValue = new Gson();
    public static final Gson gson = new Gson();


    // 主函数
    public static void main(String[] args) throws Exception {
//        String appcode = "51e2e37e74ef4c2b996b65de7b1f91fe";
//
//        /**
//         * 重要提示如下:
//         * HttpUtils请从\r\n\t    \t* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java\r\n\t    \t* 下载
//         *
//         * 相应的依赖请参照
//         * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
//         */
//        OkHttpClient client = new OkHttpClient.Builder().build();
//        RequestBody body = new FormBody.Builder()
//                .add("code", "6958439003076")
//                .build();
//        Request request = new Request.Builder()
//                .url("https://jumbarcode.market.alicloudapi.com/brugs/barCode/query")
//                .post(body)
//                .addHeader("Authorization", "APPCODE " + appcode)
//                .build();
//
//        Call call = client.newCall(request);
//        call.enqueue(new Callback() {
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                // 处理响应结果
//                //System.out.println(response.code());
//                String str = response.body().string();
//                Jumbarcode jumbarcode = gson.fromJson(str, Jumbarcode.class);
//                Medicinal medicinal = returnValue.fromJson("{}", Medicinal.class);
//                medicinal.dosage = jumbarcode.data.dosage;
//                medicinal.sm = jumbarcode.data.note;
//            }
//
//            @Override
//            public void onFailure(Call call, IOException e) {
//                // 处理请求失败
//                e.printStackTrace();
//            }
//        });

// 个性化参数入口，如果是并发使用，可以在这里模拟
        NewQuestion = "请根据以下内容\"磷酸奥司他韦可以与食物同服或分开服用。流感的治疗在流感症状开始的第一天或第二天（理想状态为36小时内）就应开始治疗。剂量指导成人和青少年磷酸奥司他韦在成人和13岁以上青少年的推荐口服剂量是每次75毫克，每日2次，共5天。儿童对1岁以上的儿童推荐按照下列体重-剂量表服用体重推荐剂量（服用5天）≤15千克>15-23千克>23-40千克>40千克30毫克，每日2次45毫克，每日2次60毫克，每日2次75毫克，每日2次流感的预防磷酸奥司他韦用于与流感患者密切接触后的流感预防时的推荐口服剂量为75毫克，每日1次，至少7天。同样应在密切接触后2天内开始用药。磷酸奥司他韦用于流感季节时预防流感的推荐剂量为75毫克，每日1次。有数据表明连用药物6周安全有效。\"，给出成年人的用法、剂量、剂量单位、频次的相关信息。其中用法范围如下（口服，外用，注射，吸入，眼用，耳用，鼻用）；频次范围如下（每日一次，每日两次，每日三次），要求以{'用法':'','剂量':'','剂量单位':'','频次':''}格式输出";
        //NewQuestion="请根据以下内容\"磷酸奥司他韦可以与食物同服或分开服用。流感的治疗在流感症状开始的第一天或第二天（理想状态为36小时内）就应开始治疗。剂量指导成人和青少年磷酸奥司他韦在成人和13岁以上青少年的推荐口服剂量是每次75毫克，每日2次，共5天。儿童对1岁以上的儿童推荐按照下列体重-剂量表服用体重推荐剂量（服用5天）≤15千克>15-23千克>23-40千克>40千克30毫克，每日2次45毫克，每日2次60毫克，每日2次75毫克，每日2次流感的预防磷酸奥司他韦用于与流感患者密切接触后的流感预防时的推荐口服剂量为75毫克，每日1次，至少7天。同样应在密切接触后2天内开始用药。磷酸奥司他韦用于流感季节时预防流感的推荐剂量为75毫克，每日1次。有数据表明连用药物6周安全有效。\"，分析成年人的用法、剂量、剂量单位、频次的相关信息。其中用法范围如下（口服，外用，注射，吸入，眼用，耳用，鼻用）；频次范围如下（每日一次，每日两次，每日三次），要求以{'用法':'','剂量':'','剂量单位':'','频次':''}格式输出";
        // 构建鉴权url
        String authUrl = null;
        try {
            authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        OkHttpClient client2 = new OkHttpClient.Builder().build();
        System.out.println(authUrl);
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        totalAnswer = "";
        WebSocket webSocket = client2.newWebSocket(request, new BigModel());
        //System.out.println(medicinal.toString());
    }

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        super.onOpen(webSocket, response);
        System.out.print("大模型：");
        try {
            JSONObject requestJson = new JSONObject();

            JSONObject header = new JSONObject();  // header参数
            header.put("app_id", appid);
            header.put("uid", UUID.randomUUID().toString().substring(0, 10));

            JSONObject parameter = new JSONObject(); // parameter参数
            JSONObject chat = new JSONObject();
            chat.put("domain", "general");
            chat.put("temperature", 0.1);
            chat.put("max_tokens", 2048);
            parameter.put("chat", chat);

            JSONObject payload = new JSONObject(); // payload参数
            JSONObject message = new JSONObject();
            JSONArray text = new JSONArray();

            // 最新问题
            RoleContent roleContent = new RoleContent();
            roleContent.role = "user";
            roleContent.content = NewQuestion;
            text.add(JSON.toJSON(roleContent));

            message.put("text", text);
            payload.put("message", message);

            requestJson.put("header", header);
            requestJson.put("parameter", parameter);
            requestJson.put("payload", payload);
            System.err.println(requestJson); // 可以打印看每次的传参明细
            webSocket.send(requestJson.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // System.out.println(userId + "用来区分那个用户的结果" + text);
        JsonParse myJsonParse = gson.fromJson(text, JsonParse.class);
        if (myJsonParse.header.code != 0) {
            System.out.println("发生错误，错误码为：" + myJsonParse.header.code);
            System.out.println("本次请求的sid为：" + myJsonParse.header.sid);
            webSocket.close(1000, "");
        }
        List<Text> textList = myJsonParse.payload.choices.text;
        for (Text temp : textList) {
            System.out.print(temp.content);
            totalAnswer = totalAnswer + temp.content;
        }
        if (myJsonParse.header.status == 2) {
            //wsCloseFlag = true;
            webSocket.close(1000, "");
        }
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        super.onFailure(webSocket, t, response);
        try {
            if (null != response) {
                int code = response.code();
                System.out.println("onFailure code:" + code);
                System.out.println("onFailure body:" + response.body().string());
                if (101 != code) {
                    System.out.println("connection failed");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    // 鉴权方法
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

    class Medicinal {
        String yf;
        String yl;
        String fs;
        String sm;
        String dosage;
    }

    class Jumbarcode {
        Data data;
    }

    class Data {
        String dosage;
        String note;
    }


    //返回的json结果拆解
    class JsonParse {
        Header header;
        Payload payload;
    }

    class Header {
        int code;
        int status;
        String sid;
    }

    class Payload {
        Choices choices;
    }

    class Choices {
        List<Text> text;
    }

    class Text {
        String role;
        String content;
    }

    class RoleContent {
        String role;
        String content;

        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}